#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<netdb.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/time.h>
#include<fcntl.h>
#include<iostream>
#include<unistd.h>

#include"getip.h"

using namespace std;
const int BUF_SIZE = 1024;
const int BUF_CONTENT = 1024*1024;
const int DEFAULT_TIMEOUT = 30;
#define HTTP_VERSION  "HTTP/1.0"
#define DEFAULT_USER_AGENT "Lee"
#define  VERSION "1.0"
int hideUserAgent = 0;
int timeout = DEFAULT_TIMEOUT;
char * userAgent = NULL;

int checkBufSize(char **buf, int *bufsize, int more)
{
	char *tmp;
	int roomLeft = *bufsize - (strlen(*buf) + 1);

	if(roomLeft > more) return 0;

	tmp = (char *)realloc(*buf, *bufsize + more + 1);
	if(tmp == NULL) return -1;

	*buf = tmp;
	*bufsize += more + 1;
	return 0;
}

int main()
{
	string strUrl = "www.baidu.com";
	char *tmp, *url, *requestBuf,*pageBuf;
	const char* host,*path;
	int bytesRead = 0, bufsize = BUF_SIZE;
	int ret = -1, tempSize,selectRet;
	host = "www.google.com";
	path = "";
	const char * ip = GetIpByHost(host);
	// head content
	url = strdup(strUrl.c_str());
	if(url==NULL){
		cout<<"strdup error"<<endl;
		return -1;
	}
	requestBuf = (char*)malloc(bufsize);

	if(requestBuf == NULL){	
		free(url);
		{
			free(url);
		}
		cout<< "can not allocate enought memory for requestBuf" << endl;
		return -1;
	}
	requestBuf[0] = 0;

	if( strlen(path) < 1 ){
	/* The url has no '/' in it, assume the user is making a root-level
                 *      request */
		tempSize = strlen("GET /") + strlen(HTTP_VERSION) +2;

		if(checkBufSize(&requestBuf, &bufsize, tempSize) ||
			snprintf(requestBuf, bufsize, "GET / %s\r\n", 
			HTTP_VERSION) < 0 )
		{
			if (url)
			{
				 free(url); url=NULL;
			}
			if (requestBuf)
			{
				 free(requestBuf); requestBuf=NULL;
			}
			cout << "1.checkBuffSize(&requestBuf..) error" << endl;
			return -1;
		}

	}else{
		tempSize = strlen("GET ") + strlen(path) + strlen(HTTP_VERSION) + 4;

		if(checkBufSize(&requestBuf, &bufsize, tempSize) ||
			snprintf(requestBuf, bufsize, "GET %s %s\r\n", 
			path, HTTP_VERSION) < 0)
		{
			if (url)
			{
				 free(url); url=NULL;
			}
			if (requestBuf)
			{
				 free(requestBuf); requestBuf=NULL;
			}
			cout << "2._checkBuffSize(&requestBuf..) error" << endl;
			return -1;
		}

	}


/* Use Host: even though 1.0 doesn't specify it.  Some servers
 *      won't play nice if we don't send Host, and it shouldn't hurt anything */
	tempSize = (int)strlen("Host: ") + (int)strlen(host) + 3;/* +3 for "\r\n\0" */

	if(checkBufSize(&requestBuf, &bufsize, tempSize + 128)){
		if (url)
		{
			 free(url); url=NULL;
		}
		if (requestBuf)
		{
			 free(requestBuf); requestBuf=NULL;
		}
		cout << "3._checkBuffSize(&requestBuf..) error" << endl;
		return -1;
	}

	strcat(requestBuf, "Host: ");
	strcat(requestBuf, host);
	strcat(requestBuf, "\r\n");

	if(!hideUserAgent && userAgent == NULL) {

		tempSize = (int)strlen("User-Agent: ") +
			(int)strlen(DEFAULT_USER_AGENT) + (int)strlen(VERSION) + 4;
		if(checkBufSize(&requestBuf, &bufsize, tempSize)) {
			if (url)
			{
			 	free(url); url=NULL;
			}
			if (requestBuf)
			{
			 	free(requestBuf); requestBuf=NULL;
			}
			cout << "4._checkBuffSize(&requestBuf..) error" << endl;
			return -1;
		}
		strcat(requestBuf, "User-Agent: ");
		strcat(requestBuf, DEFAULT_USER_AGENT);
		strcat(requestBuf, "/");
		strcat(requestBuf, VERSION);
		strcat(requestBuf, "\r\n");

	} else if(!hideUserAgent) {

		tempSize = (int)strlen("User-Agent: ") + (int)strlen(userAgent) + 3;
		if(checkBufSize(&requestBuf, &bufsize, tempSize)) {
			if (url)
			{
			 	free(url); url=NULL;
			}
			if (requestBuf)
			{
			 	free(requestBuf); requestBuf=NULL;
			}
			cout << "5._checkBuffSize(&requestBuf..) error" << endl;
			return -1;
		}
		strcat(requestBuf, "User-Agent: ");
		strcat(requestBuf, userAgent);
		strcat(requestBuf, "\r\n");
	}

	tempSize = (int)strlen("Connection: Keep-Alive\r\n\r\n");
	if(checkBufSize(&requestBuf, &bufsize, tempSize)) {
		if (url)
		{
		 	free(url); url=NULL;
		}
		if (requestBuf)
		{
		 	free(requestBuf); requestBuf=NULL;
		}
		cout << "6._checkBuffSize(&requestBuf..) error" << endl;
		return -1;
	}

	strcat(requestBuf, "Connection: Keep-Alive\r\n\r\n");


	/* Now free any excess memory allocated to the buffer */
	tmp = (char *)realloc(requestBuf, strlen(requestBuf) + 1);
	if(tmp == NULL){
		if (url)
		{
		 	free(url); url=NULL;
		}
		if (requestBuf)
		{
		 	free(requestBuf); requestBuf=NULL;
		}
		cout << "realloc for tmp error" << endl;
		return -1;
	}
	requestBuf = tmp;
	cout<<"write buf head is:"<<requestBuf<<endl;


	// socket connect
	int port = 80;
	int sock;
	//const char * ip = "202.108.22.5";
	unsigned long inaddr = (unsigned long)inet_addr(ip);
	struct sockaddr_in cli;
	sock = socket(AF_INET,SOCK_STREAM,0);
	cli.sin_family = AF_INET;
	cli.sin_port = htons(port);
	memcpy((char*)&cli.sin_addr,(char*)&inaddr,sizeof(inaddr));
	int status = connect(sock,(struct sockaddr *)&cli,sizeof(struct sockaddr));


	//write and read web data
	ret = write(sock,requestBuf,strlen(requestBuf));
	if(ret==0)
	{
		cout<<"requestBuf is:"<<requestBuf<<endl;
		cout<<"write nothing"<<endl;
		if(url)
		{
			free(url);
			url =NULL;
		}
		if(requestBuf)
		{
			free(requestBuf);
			requestBuf =NULL;
		}
		
		close(sock);
		return -1;
	}
	char headerBuf[BUF_SIZE];
	memset(headerBuf,0,BUF_SIZE);
	ret = read(sock,headerBuf,BUF_SIZE);
	if(ret==-1){
		cout<<"read error"<<endl;
	}
	cout<<headerBuf<<endl;

	// read web page content 
	pageBuf = (char*)malloc(BUF_CONTENT);
	if(pageBuf==NULL)
	{
		cout<<"malloc page buf error"<<endl;
		return -1;
	}

	ret = read(sock,pageBuf,BUF_CONTENT);
	cout<<"Page content is:"<<pageBuf<<endl;


	return 0;
}
